package cs.android.view;

import static cs.android.lang.AndroidLang.event;
import static cs.java.lang.Lang.fire;
import static cs.java.lang.Lang.list;
import static cs.java.lang.Lang.no;

import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import cs.android.ActivityView;
import cs.android.viewbase.ActivityViewBase;
import cs.android.viewbase.IsView;
import cs.java.collections.List;
import cs.java.event.Event;
import cs.java.lang.Factory;

public class DataListPresenter<RowType> extends ActivityViewBase {
	private final List<RowType> dataList = list();
	private final Event<List<RowType>> onLoad = event();
	private final ListAdapter listAdapter = new ListAdapter();
	private final Factory<RowView<RowType>> viewFactory;
	private int savedSelectionOffest;
	private int savedSelectionIndex;

	public <Parent extends ActivityView & Factory<RowView<RowType>>> DataListPresenter(Parent parent) {
		super(parent);
		this.viewFactory = parent;
	}

	public <Parent extends ActivityView & Factory<RowView<RowType>>> DataListPresenter(Parent parent,
			int listViewId) {
		super(parent, listViewId);
		this.viewFactory = parent;
	}

	@Override protected void onPause() {
		super.onPause();
		saveSelection();
	}

	@Override protected void onResume() {
		super.onResume();
		if (dataList.hasContents()) {
			asListView().setAdapter(listAdapter);
			asListView().setSelectionFromTop(savedSelectionIndex, savedSelectionOffest);
		}
	}

	private int getItemsCount() {
		return dataList.size();
	}

	private View listAdapterGetView(int position, View view) {
		RowView<RowType> rowView;
		if (no(view)) {
			rowView = viewFactory.create();
			view = rowView.asView();
			view.setTag(rowView);
		} else rowView = (RowView<RowType>) view.getTag();
		rowView.load(dataList.get(position));
		return view;
	}

	private void saveSelection() {
		savedSelectionIndex = asListView().getFirstVisiblePosition();
		View view = asListView().getChildAt(0);
		savedSelectionOffest = view == null ? 0 : view.getTop();
	}

	public void clear() {
		dataList.clear();
		listAdapter.notifyDataSetChanged();
	}

	public List<RowType> getData() {
		return dataList;
	}

	public Event<List<RowType>> getOnLoad() {
		return onLoad;
	}

	public void load(List<RowType> list) {
		dataList.addAll(list);
		listAdapter.notifyDataSetChanged();
		fire(onLoad, list);
	}

	public void prependData(RowType status) {
		dataList.add(0, status);
		listAdapter.notifyDataSetChanged();
	}

	public void reload(List<RowType> list) {
		dataList.clear();
		asListView().setAdapter(listAdapter);
		load(list);
	}

	public void setEmptyView(int layoutId) {
		asListView().setEmptyView(inflateLayout(layoutId));
	}

	public void setEmptyView(IsView view) {
		asListView().setEmptyView(view.asView());
		((ViewGroup) asView().getParent()).addView(view.asView());
	}

	private class ListAdapter extends BaseAdapter {

		public int getCount() {
			return getItemsCount();
		}

		public Object getItem(int position) {
			return dataList.get(position);
		}

		public long getItemId(int position) {
			return position;
		}

		public View getView(int position, View view, ViewGroup parent) {
			return listAdapterGetView(position, view);
		}
	}

}
